/*______________________________________________________*/
/*				   Slot Manager GetInfo			     	*/
/*                          by                          */
/*                  RICHARD P. COLLYER                  */
/*                       01/16/89                       */
/*______________________________________________________*/

/*********************************************************************



 File				:	mbGetsInfo.p
 Author				:	GN	08/13/86
 Mod History		:	RPC	02/01/89	  convert to MPW 3.0 C interfaces and 
 											overhalled the user interface.



Well, here is a cheesy sample that checks the slots, and displays a
partial summary of what is in the slots. It doesn't go as far as getting
to the vendor info, that is something I'll fix up later.  It will show
you how to use the slot manager, though.

The user interface is hideous, of course.  It uses writelns, doesn't
update, etc.  I'd shoot myself if I tried to ship this, but right now,
it is an in house experiment only.  I'll make it real in my copious free
time (heh, heh).

Basically, the slot manager is very flexible.  So much so, that a given
call may not the right one, just one that works.  Since you should never
hard code to a slot number, or even a board id (since you may revise the
board someday, and still want your software to be compatible, typically
you ask the slot manager for sResources, and it will tell you which
slot it finds them in.	An sResource can be thought of as a function
the card can perform.  The board id happens to be the most basic case
of functions - that of being a board. For instance, if you wrote a
terminal app, you don't want to have your app go out and look for one
board id.  That locks you into ONE hardware product. Your app could
better ask the slot manager for a particular sResource that had an
sRsrc_Type of, say,

Category  := CatCommunication
cType     := TypModem
DrvrSW    := {don't care - mask this out}
DrvrHw    := {don't care - mask this out}

(you can mask out any type, if you don't care what it is)

That gets you to a card that can perform the function of a modem.  But, there
are two more fields to the sRsrc_Type - a software driver field and a
hardware driver field. If you wanted to check to see if this modem had a driver
you could talk to (let us imagine there was a Hayes-compatible command sort of 
driver defined), and a driver id had been defined for this particular driver, you 
would check additionally for the the software driver field, say,

Category  := CatCommunication
cType     := TypModem
DrvrSW    := DrSWHayes
DrvrHw    := {don't care - mask this out}

(in other words specify the Cat, Type, DrSw, and mask out the DrHW)

Your app shouldn't care what the underlying hardware is, unless it
absolutely had to, so you could be compatible with future revs of the
board, and even other manufacturer's boards (say, other Hayes compatible
modem cards). You win by not having to rev your app and by actually
expanding the market, by appealing to more customers.


Who assigns the board ids and sRsrc_Type values?

We (MacDTS) keep the database of the values for the Category, Type, Sw and
HW ids, as well as board ids.  We don't make any values public.  If a
developer desired to have values published, the developer would most likely 
do the publishing anyway.  In short, the database is extremely confidential.

If you have a dedicated app that must pound on a given card without using a
driver, that is a different matter. Hopefully, though cards have a driver
that you can call without having to worry about the hardware.  That driver can
be in ROM, in an init, or possibly even in the application (although this last
case kind of defeats the purpose of separating the application from the driver). 
If a card manufacturer defines a software interface and publishes
it (for example the Hayes compatible software set), then other developers can 
develop products for it.
*/


#include	<CType.h>
#include	<Quickdraw.h>
#include	<Windows.h>
#include	<OSUtils.h>
#include	<desk.h>
#include	<dialogs.h>
#include	<Errors.h>
#include	<Events.h>
#include	<Memory.h>
#include	<Menus.h>
#include	<SegLoad.h>
#include	<Slots.h>
#include	<ToolUtils.h>

extern _DataInit();

#define	TRUE			0xFF
#define	FALSE			0
#define	VERSION			1
#define	SR_BIT			0

#define	appleID			128			
#define	appleMenu		0
#define	aboutMeCommand	1

#define	fileID			129
#define	nine			1
#define	a				2
#define	b				3
#define	c				4
#define	d				5
#define	e				6
#define	General			8
#define	quitCommand 	10

#define	aboutMeDLOG		128
#define	okButton		1
#define	authorItem		2
#define	languageItem	3

int					yieldTime;
Rect				TotalRect;
WindowPtr			whichWindow, myWindow, myWindow1;
MenuHandle			mymenu1, mymenu2, mymenu0;
EventRecord 		myEvent;
Boolean				DoneFlag;
SpBlockPtr			mySpBlockPtr;
SpBlock				mySpBlock;
SInfoRecord			mySInfoRecord;
SInfoRecPtr			mySInfoRecPtr;
FHeaderRec			myFHeaderRec;
Boolean				first;
PicHandle			GenPict, GetPict;
RGBColor			black, white;

/*______________________________________________________*/
/*            Convert Decimal numbers to Hex            */
/*______________________________________________________*/
void Dec2Hex(Num, sig)
long	Num, sig;
{
	int				Rem[7], i, Index;
	char			*tempStrPtr, store[256];
	
	tempStrPtr = &store; /* initalize string memory */
	
	drawstring ("          "); /* check for negative number and convert */
	if (Num < 0)
		drawstring ("-");
	Num = abs (Num);
	
	Num = Num & sig; /* dispose of uninteresting bytes */
		
	/* convert Num to an array of base 16 numbers */
	i = 0;
	do {
		Rem[i] = Num % 16;
		Num /= 16;
		++i;
		} while (Num >= 16);
	Rem[i] = Num;
	
	/* draw the base 16 numbers as the Hex conversion of Num */
	for (Index = i; Index >= 0; --Index)
		switch (Rem[Index]) {
			case 10:
				drawstring ("A");
				break;
			case 11:
				drawstring ("B");
				break;
			case 12:
				drawstring ("C");
				break;
			case 13:
				drawstring ("D");
				break;
			case 14:
				drawstring ("E");
				break;
			case 15:
				drawstring ("F");
				break;
			default:
				numtostring (Rem[Index], tempStrPtr);
				drawstring (tempStrPtr);
				break;
			}
	drawstring ("(hex)");
	return;
}

/*______________________________________________________*/
/*            Look up Error code in Resource            */
/*   FindError : Given an error, write out the prompt   */
/*		string, then look up the errors corresponding   */
/*		 error string (located in a string resource)    */
/*		             and write it out.		         	*/
/*______________________________________________________*/
void FindError(error)
int		error;
{
	char	*ErrorString, storage[256];
	int		Index;
	
	ErrorString = &storage;
	
	if (error <= -290 && error >= -293) {
		Index = abs(error) - 289;
		getindstring (ErrorString, 130, Index);
		}
	else if (error <= -300 && error >= -320) {
		Index = abs(error) - 299;
		getindstring (ErrorString, 131, Index);
		}
	else if (error <= -330 && error >= -351) {
		Index = abs(error) - 329;
		getindstring (ErrorString, 132, Index);
		}
	else if (error = -360) {
		Index = 1;
		getindstring (ErrorString, 133, Index);
		}
	else if (error = -400) {
		Index = 1;
		getindstring (ErrorString, 134, Index);
		}
	else if (error <= -500) {
		Index = abs(error) - 499;
		getindstring (ErrorString, 135, Index);
		}
	else {
		numtostring (error, ErrorString);
		drawstring ("(");
		drawstring (ErrorString);
		drawstring (")");
		ErrorString = "some unknown error";
		}
	drawstring (ErrorString);
	return;
}

/*______________________________________________________*/
/*            Write out the slot Number                 */
/*______________________________________________________*/
void FindSlot(Ind)
int		Ind;
{
	/* draw which slot is being looked at in the general information window */
	switch (Ind) {
		case 9:
			MoveTo (20,20);
			drawstring ("Slot Number 9 : ");
			break;
		case 10:
			MoveTo (20,40);
			drawstring ("Slot Number A : ");
			break;
		case 11:
			MoveTo (20,60);
			drawstring ("Slot Number B : ");
			break;
		case 12:
			MoveTo (20,80);
			drawstring ("Slot Number C : ");
			break;
		case 13:
			MoveTo (20,100);
			drawstring ("Slot Number D : ");
			break;
		case 14:
			MoveTo (20,120);
			drawstring ("Slot Number E : ");
			break;
		default:
			break;
		}
	return;
}

/*______________________________________________________*/
/*          Get the General Slot information            */
/*   fill in the general information window for slots   */
/*                   other than zero      				*/
/*______________________________________________________*/
void GenOtherInfo()
{
	int		Index;
	OSErr	err;
	
	for (Index = 9; Index <= 14; ++Index) {
		/* init parameters for SReadInfo */
		mySInfoRecPtr = &mySInfoRecord; /* provide space for results */
		mySpBlockPtr = &mySpBlock;
		mySpBlockPtr->spResult = (long) mySInfoRecPtr;
		mySpBlockPtr->spSlot = Index; /* which slot to look at */
		
		err = SReadInfo (mySpBlockPtr);
		
		if (!err) {
			if (mySInfoRecPtr->siInitStatusA == smEmptySlot) {
				FindSlot(Index);
				drawstring ("got initialization error : ");
				FindError(mySInfoRecord.siInitStatusA);
				}
			else {
				EnableItem(mymenu1, Index - 8);
		
				/* init parameters for sNextTypesRsrc, look for card info of the following type */
				/* Look in slot (Index) and drawstring the name of the card */
				mySpBlockPtr = &mySpBlock;
				mySpBlockPtr->spSlot = Index;
				mySpBlockPtr->spID = 0;
				mySpBlockPtr->spExtDev = 0;
				mySpBlockPtr->spCategory = 1;
				mySpBlockPtr->spCType = 0;
				mySpBlockPtr->spDrvrSW = 0;
				mySpBlockPtr->spDrvrHW = 0;
				
				err = SNextTypeSRsrc (mySpBlockPtr);
				
				if (!err) {
					/* init parameters for SGetCString */
					mySpBlockPtr = &mySpBlock;
					mySpBlockPtr->spID = 2; /* sRsrc_Name */

					/* write out information */
					err = SGetCString (mySpBlockPtr);
					
					if (!err) {
						FindSlot(Index);
						drawstring ((char *) (mySpBlockPtr->spResult));
						}
					else {
						/* report error */
						FindSlot(Index);
						drawstring ("Error doing SGetCString : ");
						FindError (err);
						}
					}
				else {
					/* report error */
					FindSlot(Index);
					drawstring ("Error doing SNextTypeSRsrc : ");
					FindError (err);
					}
				}
			}
		else {
			/* report error */
			FindSlot(Index);
			drawstring ("Error doing SReadInfo : ");
			FindError (err);
			}
		}
	return;
}

/*______________________________________________________*/
/*             get screen and put in Pict               */
/*           This is used for update events             */
/*______________________________________________________*/
void getter(currentPICT, theWindow)
PicHandle	*currentPICT;
WindowPtr	*theWindow;
{
	KillPicture (*currentPICT);
	RGBForeColor(&black);
	RGBBackColor(&white);
	*currentPICT = OpenPicture(&(*theWindow)->portRect);
	CopyBits (&(*theWindow)->portBits, &(*theWindow)->portBits,
				&(*theWindow)->portRect, 
				&(*theWindow)->portRect, 
				srcCopy, nil);
	ClosePicture();
	return;
}

/*______________________________________________________*/
/*             get Pict and put in screen               */
/*           This is used for update events             */
/*______________________________________________________*/
void putter(currentPICT, theWindow)
PicHandle	*currentPICT;
WindowPtr	*theWindow;
{
	WindowPtr	tempPtr;
	
	GetPort (&tempPtr);
	SetPort (*theWindow);
	DrawPicture (*currentPICT, &(*theWindow)->portRect);
	SetPort (tempPtr);
	return;
}

/*______________________________________________________*/
/*              Get General Information                 */
/*    GenInfo : Display the slot information record     */
/*	    for all the slots.  Uses the fact that          */
/*	   the (required) board resource ALWAYS has         */
/*	   an sRsrc_Type of CatBoard, TypeBoard,0,0.        */
/*     The other sRsrc_Types will have different        */
/*          Cat, Typ, drvrsw, and drvrhw.				*/
/*______________________________________________________*/
void GenInfo()

{
	/* Get information about slots 9 - E */
	
	GenOtherInfo();

	/* save window to a PICT for use during updates */
	getter(&GenPict, &myWindow);
	return;
}

/*______________________________________________________*/
/*             Get Specific Information                 */
/* GetInfo : Display slot info.
 routines used:

theErr := sNextTypesRsrc(myspBlkPtr); {find info only about a specified sResource type}
	 INPUT:
	 mySpBlock.spSlot 	 - slot number to start from
	 mySpBlock.Id		    - sResource list id number to start from
	 mySpBlock.spExtDev	 -
	 mySpBlock.spTBMask	 - mask for desired sResource types
	 mySpBlock.spCategory - sResource type fields
	 mySpBlock.spCType	 - sResource type fields
	 mySpBlock.spDrvrSW	 - sResource type fields
	 mySpBlock.spDrvrSW	 - sResource type fields
	 mySpBlock.spHWDev	 -
	 RETURNED:
	 mySpBlock.spSlot 	 - slot number of FOUND sResource
	 mySpBlock.Id		    - sResource list id number
	 mySpBlock.spExtDev	 -
	 mySpBlock.spsPointer -
	 mySpBlock.spRefNum	 - driver reference number
	 mySpBlock.spIOReserved - slot resource table ioReserved field
	 mySpBlock.spCategory	- sResource type fields
	 mySpBlock.spCType	 - sResource type fields
	 mySpBlock.spDrvrSW	 - sResource type fields
	 mySpBlock.spDrvrSW	 - sResource type fields
	 mySpBlock.spHWDev	 -

theErr := sRsrcInfo(myspBlkPtr); {usually used to get driver refnum}
	 INPUT:
	 mySpBlock.spSlot 	- slot number
	 mySpBlock.Id		- id of the sResource
	 mySpBlock.spExtDev	 - external device identifier
	 RETURNED:
	 mySpBlock.spsPointer	- sResource list pointer
	 mySpBlock.spCategory	- sResource type fields
	 mySpBlock.spCType	 - sResource type fields
	 mySpBlock.spDrvrSW	 - sResource type fields
	 mySpBlock.spDrvrSW	 - sResource type fields
	 mySpBlock.spRefNum	 - driver reference number
	 mySpBlock.spIOReserved - slot resource table ioReserved field
	 mySpBlock.spHWDev	 -

theErr :=  SReadWord(myspBlkPtr);
	  INPUT:
	  mySpBlock.spsPointer - pointer to the sResource list
	  mySpBlock.spID	 - id within that sResource list
	  RETURNED:
	  mySpBlock.spResult  - the 16 bit value returned in low-order word of spResult (spResult=long)

theErr :=  SReadFHeader(myspBlkPtr);
	  INPUT:
	  mySpBlock.spSlot	- slot number
	  mySpBlock.spResult  - point to result area (which is an FHeaderRec)
	  RETURNED:
	  mySpBlock.spResult  -
	  mySpBlock.spResult is a pointer to FHeader record, with the following structure:
	  FHeaderRec = PACKED RECORD
		fhDirOffset: LONGINT;	{offset to directory}
		fhLength: LONGINT;	 {length of ROM}
		fhCRC: LONGINT;	  {CRC}
		fhROMRev: SignedByte;	{revision of ROM}
		fhFormat: SignedByte;	{format - 2}
		fhTstPat: LONGINT;	 {test pattern}
		fhReserved: SignedByte;   {reserved}
		fhByteLanes: SignedByte;  {ByteLanes}
		END;

	  and of course,
	  FHeaderRecPtr = ^FHeaderRec;

theErr :=  SReadDrvrName(myspBlkPtr);
	  INPUT:
	  mySpBlock.spSlot	- slot number
	  mySpBlock.spID	 - id within that sResource list
	  mySpBlock.spResult  - the 16 bit value returned in low-order word of spResult (spResult=long)
	  RETURNED:
	  mySpBlock.spResult  - the 16 bit value returned in low-order word of spResult (spResult=long)

________________________________________________________*/
void GetInfo(WhichSlot)
int		WhichSlot;
{
	OSErr			err;
	FHeaderRecPtr	tempFHeaderRecPtr;
	char			*tempStrPtr, NameStr[256], store[256];
	int				temp;
	
	tempStrPtr = &store; /* initalize temperary string varible */
	
	if (first) {
		/* If window hasn't been opened before than open it */
		myWindow1 = GetNewWindow(131, nil, (WindowPtr) -1);
		SetPort (myWindow1);
		first = FALSE;
		}
	else {
		/* If window is already open then make it the front most window */
		SelectWindow (myWindow1);
		SetPort (myWindow1);
		EraseRect (&(myWindow1->portRect));
		}
	
	MoveTo (20,20);
	drawstring ("SLOT INFORMATION for Slot ");
	switch (WhichSlot) {
		case 9:
			drawstring (" 9 : ");
			break;
		case 10:
			drawstring (" A : ");
			break;
		case 11:
			drawstring (" B : ");
			break;
		case 12:
			drawstring (" C : ");
			break;
		case 13:
			drawstring (" D : ");
			break;
		case 14:
			drawstring (" E : ");
			break;
		default:
			break;
		}
	
	if (WhichSlot != 0) {
		mySpBlockPtr = &mySpBlock;
		mySpBlockPtr->spSlot = WhichSlot;
		mySpBlockPtr->spResult = (long) &myFHeaderRec;
		
		err = SReadFHeader (mySpBlockPtr);
		
		if (!err) {
			/* drawstring the Format Header information listed in reverse order from */
			/* Cards and Driver book Fig 8-3 page 8-5 (Firmware Structure) */
			tempFHeaderRecPtr = (FHeaderRecPtr) mySpBlock.spResult;
			
			MoveTo (20,40);
			drawstring ("fhDirOffset = ");
			numtostring (tempFHeaderRecPtr->fhDirOffset, tempStrPtr);
			drawstring (tempStrPtr);
			Dec2Hex (tempFHeaderRecPtr->fhDirOffset, 0xFFFFFFFF);

			MoveTo (20,60);
			drawstring ("fhLength = ");
			numtostring (tempFHeaderRecPtr->fhLength, tempStrPtr);
			drawstring (tempStrPtr);
			Dec2Hex (tempFHeaderRecPtr->fhLength, 0xFFFFFFFF);

			MoveTo (20,80);
			drawstring ("fhCRC = ");
			numtostring (tempFHeaderRecPtr->fhCRC, tempStrPtr);
			drawstring (tempStrPtr);
			Dec2Hex (tempFHeaderRecPtr->fhCRC, 0xFFFFFFFF);

			MoveTo (20,100);
			drawstring ("fhROMRev = ");
			numtostring (tempFHeaderRecPtr->fhROMRev, tempStrPtr);
			drawstring (tempStrPtr);
			Dec2Hex (tempFHeaderRecPtr->fhROMRev, 0xFFFFFFFF);

			MoveTo (20,120);
			drawstring ("fhFormat = ");
			numtostring (tempFHeaderRecPtr->fhFormat, tempStrPtr);
			drawstring (tempStrPtr);
			Dec2Hex (tempFHeaderRecPtr->fhFormat, 0xFFFFFFFF);

			MoveTo (20,140);
			drawstring ("fhTstPat = ");
			numtostring (tempFHeaderRecPtr->fhTstPat, tempStrPtr);
			drawstring (tempStrPtr);
			Dec2Hex (tempFHeaderRecPtr->fhTstPat, 0xFFFFFFFF);

			MoveTo (20,160);
			drawstring ("fhReserved = ");
			numtostring (tempFHeaderRecPtr->fhReserved, tempStrPtr);
			drawstring (tempStrPtr);
			Dec2Hex (tempFHeaderRecPtr->fhReserved, 0xFFFFFFFF);

			MoveTo (20,180);
			drawstring ("fhByteLanes = ");
			temp = tempFHeaderRecPtr->fhByteLanes & 0x000000FF;
			numtostring (temp, tempStrPtr);
			drawstring (tempStrPtr);
			Dec2Hex (temp, 0x000000FF);
			}
		else {
			/* report error */
			MoveTo (20,40);
			drawstring ("Error doing SReadFHeader : ");
			FindError (err);
			}

		mySpBlockPtr = &mySpBlock;
		mySpBlockPtr->spSlot = WhichSlot;
		mySpBlockPtr->spID = 128; /* bogas hard coding, assumes only one functional resource */
		/* I should use sNextsRsrc call and look for all functional resources, maybe in the next rev*/
		mySpBlockPtr->spResult = NameStr; /* provide space for card's name */
			
		err = SReadDrvrName (mySpBlockPtr);
			
		if (!err) {
			MoveTo (20,200);
			drawstring ("The driver name is: ");
			DrawString (NameStr);
			}
		else {
			MoveTo (20,200);
			drawstring ("Error doing SReadDrvrName : ");
			FindError (err);
			}
		}
		
	mySpBlockPtr = &mySpBlock;
	mySpBlockPtr->spSlot = WhichSlot;
	mySpBlockPtr->spID = 0;
	mySpBlockPtr->spExtDev = 0;
	mySpBlockPtr->spCategory = 1;
	mySpBlockPtr->spCType = 0;
	mySpBlockPtr->spDrvrSW = 0;
	mySpBlockPtr->spDrvrHW = 0;
	
	err = SNextTypeSRsrc (mySpBlockPtr);
	
	if (!err) {
		mySpBlockPtr->spID = 32; /* look for Board ID card design id#, See page 8-17 Cards and Drivers */
		err = SReadWord (mySpBlockPtr);
		
		if (!err) {
			MoveTo (20,220);
			drawstring ("The Board id is: ");
			temp = mySpBlockPtr->spResult & 0x0000FFFF;
			numtostring (temp, tempStrPtr);
			drawstring (tempStrPtr);
			Dec2Hex (mySpBlockPtr->spResult, 0x0000FFFF);
			
			MoveTo (20,240);
			drawstring ("The Board is: ");
				
			mySpBlockPtr = &mySpBlock;
			mySpBlockPtr->spID = 2; /* sRsrc_Name, Name of the sResource */
			
			err = SGetCString (mySpBlockPtr);
			if (!err)
				drawstring ((char *) mySpBlockPtr->spResult);
			
			mySpBlockPtr = &mySpBlock;
			mySpBlockPtr->spID = 36; /* Vendor part number, name, and so forth */
			
			if (WhichSlot != 0) {
				err = SFindStruct (mySpBlockPtr);
				
				if (!err) {
					/* The following is stored in the VendorInfo field of the Board sResource */
					/* for more information about the VendorInfo field see page 8-19 of the */
					/* Cards and Drivers manual */
					MoveTo (20,260);
					mySpBlockPtr = &mySpBlock;
					mySpBlockPtr->spID = 1; /* the card vendor's design identification */
					err = SGetCString (mySpBlockPtr);
					if (!err) {
						drawstring ("Vendor ID is : ");
						drawstring ((char *) mySpBlockPtr->spResult);
						}
					else {
						drawstring ("Error doing SGetCString : ");
						FindError (err);
						}
					
					MoveTo (20,280);
					mySpBlockPtr = &mySpBlock;
					mySpBlockPtr->spID = 2; /* the individual card's serial number */
					err = SGetCString (mySpBlockPtr);
					if (!err) {
						drawstring ("Serial Num is : ");
						drawstring ((char *) mySpBlockPtr->spResult);
						}
					else {
						drawstring ("Error doing SGetCString : ");
						FindError (err);
						}
					
					MoveTo (20,300);
					mySpBlockPtr = &mySpBlock;
					mySpBlockPtr->spID = 3; /* the card design's revision level */
					err = SGetCString (mySpBlockPtr);
					if (!err) {
						drawstring ("Rev Level is : ");
						drawstring ((char *) mySpBlockPtr->spResult);
						}
					else {
						drawstring ("Error doing SGetCString : ");
						FindError (err);
						}
					
					MoveTo (20,320);
					mySpBlockPtr = &mySpBlock;
					mySpBlockPtr->spID = 4; /* the part number of the card */
					err = SGetCString (mySpBlockPtr);
					if (!err) {
						drawstring ("Part Num is : ");
						drawstring ((char *) mySpBlockPtr->spResult);
						}
					else {
						drawstring ("Error doing SGetCString : ");
						FindError (err);
						}
					
					MoveTo (20,340);
					mySpBlockPtr = &mySpBlock;
					mySpBlockPtr->spID = 5; /* last revision date of the card */
					err = SGetCString (mySpBlockPtr);
					if (!err) {
						drawstring ("Date is : ");
						drawstring ((char *) mySpBlockPtr->spResult);
						}
					else {
						drawstring ("Error doing SGetCString : ");
						FindError (err);
						}
					}
				else {
					MoveTo (20,260);
					drawstring ("Error doing sFindStruct : ");
					FindError (err);
					}
				}
			}
		else {
			MoveTo (20,220);
			drawstring ("Error doing SReadWord : ");
			FindError (err);
			}
		}
	else {
		MoveTo (20,220);
		drawstring ("Error doing sNextTypesRscr : ");
		FindError (err);
		}
	getter(&GetPict, &myWindow1);
	return;
}

/*______________________________________________________*/
/*                 About Prog Dialog                    */
/*______________________________________________________*/
void showAboutMeDialog()
{
	GrafPtr 	savePort;
	DialogPtr	theDialog;
	short		itemHit;

	GetPort(&savePort);
	theDialog = GetNewDialog(aboutMeDLOG, nil, (WindowPtr) -1);
	SetPort(theDialog);

	do {
		ModalDialog(nil, &itemHit);
	} while (itemHit != okButton);

	CloseDialog(theDialog);

	SetPort(savePort);
	return;
}

/*______________________________________________________*/
/*                 Do Menu Function                     */
/*______________________________________________________*/
void doCommand(mResult)
	long	mResult;
{
	int 					theMenu, theItem;
	char					daName[256];
	GrafPtr 				savePort;

	theItem = LoWord(mResult);
	theMenu = HiWord(mResult);
	
	switch (theMenu) {
/*______________________________________________________*/
/*                    Do Apple Menu                     */
/*______________________________________________________*/
		case appleID:
			if (theItem == aboutMeCommand)
				showAboutMeDialog();
			else {
				GetItem(mymenu0, theItem, daName);
				GetPort(&savePort);
				(void) OpenDeskAcc(daName);
				SetPort(savePort);
			}
			break;
/*______________________________________________________*/
/*                     Do File Menu                     */
/*______________________________________________________*/
		case fileID:
			switch (theItem) {
				case nine:
					GetInfo(9);
					break;
				case a:
					GetInfo(10);
					break;
				case b:
					GetInfo(11);
					break;
				case c:
					GetInfo(12);
					break;
				case d:
					GetInfo(13);
					break;
				case e:
					GetInfo(14);
					break;
				case General:
					SelectWindow(myWindow);
					SetPort((WindowPtr) myWindow);
					GenInfo();
					break;
				case quitCommand:
					DoneFlag = TRUE;
					break;
				default:
					break;
				}
			break;
		default:
			break;
		}
	HiliteMenu(0);
	return;
}

/*______________________________________________________*/
/*               Initialization traps                   */
/*______________________________________________________*/
void init()
{
	RgnHandle		tempRgn;
	
	UnloadSeg(_DataInit);
	InitGraf(&qd.thePort);
	FlushEvents(everyEvent, 0);
	InitWindows();
	InitDialogs(nil);
	InitCursor();
			
/*______________________________________________________*/
/*                     Set Rects                        */
/*______________________________________________________*/
	tempRgn = GetGrayRgn();
	HLock ((Handle) tempRgn);
	TotalRect = (**tempRgn).rgnBBox; /* this rect is used for DragWindow call */
	HUnlock ((Handle) tempRgn);

/*______________________________________________________*/
/*                    Set menus                         */
/*______________________________________________________*/
	mymenu0 = GetMenu(appleID);
	AddResMenu(mymenu0, 'DRVR');
	InsertMenu(mymenu0,0);
	mymenu1 = GetMenu(129);
	InsertMenu(mymenu1,0);
	DrawMenuBar();

/*______________________________________________________*/
/*                  Init variables                      */
/*______________________________________________________*/
	/* define black and white of copybits call */
	black.red = 0;
	black.green = 0;
	black.blue = 0;
	white.red = 65535;
	white.green = 65535;
	white.blue = 65535;
	DoneFlag = FALSE;
	first = TRUE;
	yieldTime = 0;
	return;
}

main()
{
	Boolean		track;
	char		key;
/*______________________________________________________*/
/*                   Main Event loop                    */
/*______________________________________________________*/
	init();
	myWindow = GetNewWindow(130, nil, (WindowPtr) -1);
	SetPort((WindowPtr) myWindow);
	GenInfo();
	for ( ;; ) {
		if (DoneFlag) {
			ExitToShell();
			}
		if (WaitNextEvent(everyEvent, &myEvent, yieldTime, nil)) {
			switch (myEvent.what) {
				case mouseDown:
					switch (FindWindow(myEvent.where, &whichWindow)) {
						case inSysWindow:
							SystemClick(&myEvent, whichWindow);
							break;
						case inMenuBar:
							doCommand(MenuSelect(myEvent.where));
							break;
						case inContent:
							if (whichWindow == myWindow)
								SelectWindow (myWindow);
							if (whichWindow == myWindow1)
								SelectWindow (myWindow1);
							break;
						case inDrag:
							DragWindow (whichWindow, myEvent.where, &TotalRect);
							break;
						case inGoAway:
							track = TrackGoAway (whichWindow, myEvent.where);
							if (track)
								CloseWindow (whichWindow);
							break;
						default:
							break;
						}
					break;
				case keyDown:
				case autoKey:
					key = myEvent.message & charCodeMask;
					if ( myEvent.modifiers & cmdKey )
						if ( myEvent.what == keyDown )
							doCommand(MenuKey(key));
					break;
				case updateEvt:
					if ((WindowPtr) myEvent.message == myWindow) {
						/* Update General Information Window */
						BeginUpdate((WindowPtr) myWindow);
						putter(&GenPict, &myWindow);
						EndUpdate((WindowPtr) myWindow);
						}
					if ((WindowPtr) myEvent.message == myWindow1) {
						/* Update Specific Inforamtion Window */
						BeginUpdate((WindowPtr) myWindow1);
						putter(&GetPict, &myWindow1);
						EndUpdate((WindowPtr) myWindow1);
						}
					break;
				case diskEvt:
					break;
				case activateEvt:
					break;
				case app4Evt:
					if ((myEvent.message << 31) == 0) { /* Suspend */
						yieldTime = 30;
						HideWindow((WindowPtr) myWindow);
						}
					else { /* Resume */
						yieldTime = 0;
						ShowWindow((WindowPtr) myWindow);
						SetPort((WindowPtr) myWindow);
						}
					break;
				default:
					break;
				}
			}
		}
}